package com.bjpowernode.springsecurity03.filter;

import com.bjpowernode.springsecurity03.domain.SysUser;
import com.bjpowernode.springsecurity03.util.JwtUtil;
import com.bjpowernode.springsecurity03.vo.Result;
import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

/**
 * 检查jwt
 */
@Component
public class AppJwtCheckFilter extends OncePerRequestFilter {

    @Resource
    private ObjectMapper objectMapper;


    @Resource
    private StringRedisTemplate stringRedisTemplate;


    /**
     * 1.若是登录相关请求则放行
     * 2.获取前端发送的jwt
     * 3.检查jwt
     * 4.从jwt中提取用户信息，构建用户对象，放入security
     */
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        response.setCharacterEncoding("utf-8");
        response.setContentType("application/json;charset=utf-8");

        //1.若是登录相关请求则放行
        String requestURI = request.getRequestURI();
        if (requestURI.equals("/login/doLogin")) {
            //登录请求放行
            filterChain.doFilter(request, response);
            return;
        }

        //2.获取前端发送的jwt
        //这里的authorization是：Bearer jwt
        String authorization = request.getHeader("Authorization");
        if (authorization == null) {
            Result result = new Result(-1, "token不能为空");
            String jsonStr = objectMapper.writeValueAsString(result);

            response.getWriter().write(jsonStr);
            return;
        }
        //提取jwt 注意Bearer后面有空格
        String jwt = authorization.replace("Bearer ", "");
        //3.检查jwt
        if (!JwtUtil.verify(jwt)) {
            Result result = new Result(-1, "token不合法");
            String jsonStr = objectMapper.writeValueAsString(result);

            response.getWriter().write(jsonStr);
            return;
        }


        //检查redis中的jwt
        if (!stringRedisTemplate.hasKey("jwt:" + jwt)) {
            Result result = new Result(-1, "token不合法");
            String jsonStr = objectMapper.writeValueAsString(result);

            response.getWriter().write(jsonStr);
            return;
        }


        //4.从jwt中提取用户信息，构建用户对象，放入security
        Integer userId = JwtUtil.getUserId(jwt);
        String username = JwtUtil.getUsername(jwt);
        List<String> authority = JwtUtil.getAuth(jwt);

        //将List<String>转成List<SimpleGrantedAuthority>
        List<SimpleGrantedAuthority> permissions = new ArrayList<>();
        for (String p : authority) {
            permissions.add(new SimpleGrantedAuthority(p));
        }

        //构建sysUser对象
        SysUser sysUser = new SysUser();
        sysUser.setUserId(userId);
        sysUser.setUsername(username);
        sysUser.setPermissions(permissions);

        //将SysUser填入security中,security会认为当前认证成功
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(sysUser, null, sysUser.getPermissions());
        SecurityContextHolder.getContext().setAuthentication(authenticationToken);

        //放行
        filterChain.doFilter(request, response);
    }
}
